home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk1 / semaphorestutor / sem.doc < prev    next >
Text File  |  1995-03-18  |  6KB  |  173 lines

  1. I've been looking through the Autodocs on message & signal semaphores
  2. and I find them to be a little bit lacking (I know, this has been
  3. mentioned before).  So I was hoping that I might clarify the
  4. use of them just a bit.  These programs demonstrate what I think is
  5. going on, I invite you all to try to find problems with them...  They seem
  6. OK to me but semaphores in any O/S are a really touchy area.
  7.  
  8. ----
  9.  
  10. Message based semaphores (usually refered to as just 'Semaphores') make use
  11. of the Message sending/receiving/waiting protocols.  In order to use
  12. them you must initialize a 'struct Semaphore'  if you examine just what
  13. a struct Semaphore is you'll see that it is defined as
  14.  
  15. struct Semaphore {
  16.     struct MsgPort sm_MsgPort;
  17.     WORD sm_Bids;
  18. }
  19.  
  20. (it's in <exec/semaphores.h> like all of the semaphore definitions).
  21.  
  22. To initialize it, you must allocate the memory for the structure and
  23. then do all of the usual MsgPort initialization things.  Normally
  24. CreatePort() does all of this for you but you can't use it as you have
  25. do to a slightly different initialization for a semaphore.  See the
  26. CreateSemaphore() function in the msgsem example.  You can make a
  27. semaphore public by making its MsgPort public (i.e. giving the MsgPort
  28. a name & priority and using AddPort() to add the port to the system list
  29. of named ports).  You can then find such a semaphore by using the FindPort()
  30. call... To remove the semaphore from the system you have do remove it from 
  31. the public port list using RemPort() (iff you added it to that list) and
  32. then simply free the memory allocated for the structure.
  33.  
  34. Assuming you have created the Semaphore, to use it you must allocate a
  35. message (to be used as your 'bid' for the semaphore) and port that this
  36. message will be sent to.  Initialize the mn_ReplyPort field of your
  37. message to point to your port.  You then use these two functions
  38. to lock/unlock the semaphore.
  39.  
  40. Procure(Semaphore, BidMessage)
  41. struct Semaphore *Semaphore;
  42. struct Message *BidMessage;
  43.  
  44.     Procure() returns true if the semaphore can be locked for your
  45.     use immediately.  If the semaphore cannot be locked, your
  46.     bid is queued up and when it becomes free your BidMessage
  47.     will be sent the the port you allocated (the one that nm_ReplyPort
  48.     in the BidMessage is supposed to point to).  So if you need
  49.     to get the Semaphore and you can't go on any further without
  50.     it you must do something like
  51.  
  52.     if (!Procure(semaphore,message)) {
  53.         WaitPort(message->mn_ReplyPort);
  54.         GetMsg(message->nm_ReplyPort);
  55.     }
  56.  
  57.     ... put code that needs the semaphore here ...
  58.  
  59.     This assumes that there is only one semaphore using this port
  60.     for it's replies.  Otherwise you have to be more complicated.
  61.  
  62. Vacate(Semaphore)
  63. struct Semaphore *Semaphore;
  64.  
  65.     Vacate() unlocks the semaphore so that some other Procure()
  66.     will succeed or if there is an outstanding bid then the
  67.     bid message will sent to the appropriate port.
  68.  
  69.     So much for straight Semaphores.  Now onto SignalSemaphores.
  70.  
  71. ----
  72.  
  73. SignalSemaphores seem much easier to use on the surface only they
  74. are slightly broken which makes up for this.  The AddSemaphore(),
  75. RemSemaphore() and FindSemaphore() calls all need special attention
  76. as they don't work as advertised in the Autodocs.  Other than this
  77. difficulty, signal semaphores are very easy to deal with as
  78. there are no painful initialization rituals to remember as with
  79. message semaphores above... just allocate enough memory for the
  80. SignalSemaphore and you're off to the races.
  81.  
  82. InitSemaphore(SignalSemaphore)
  83. struct SignalSemaphore *SignalSemaphore;
  84.  
  85.     Initializes a signal semaphore structure.  Use this function
  86.     for "private" semaphores (i.e. known only to tasks that
  87.     have easy access to the creator's memory).
  88.  
  89. AddSemaphore(SignalSemaphore)
  90. struct SignalSemaphore *SignalSemaphore;
  91.  
  92.     Adds the semaphore to the system list of semaphores.  You
  93.     must fill in the ss_Link.ln_{Type,Name,Pri} fields before
  94.     calling this.  AddSemaphore() calls InitSemaphore() so
  95.     you don't need to do call this yourself if you use AddSemaphore().
  96.  
  97.     N.B.  The Exec version of this function seems to be broken.
  98.     Use Dale's "hand crafted" version instead.  (it's just a
  99.     InitSemaphore() call followed by an atomic Enqueue on the
  100.     system signal semaphore list).  See example.
  101.  
  102.  
  103. RemSemaphore(SignalSemaphore)
  104. struct SignalSemaphore *SignalSemaphore;
  105.  
  106.     Removes the given semaphore from the system list of public
  107.     semaphores.
  108.  
  109.     N.B. The amiga.lib and c[32].lib bindings for this function
  110.     are broken.  You must include your own bindings for this
  111.     to work.  See example.
  112.  
  113.  
  114. struct SignalSemaphore *FindSemaphore(name)
  115. char *name;
  116.  
  117.     Search the system list for semaphores for one with the given
  118.     name.  Returns a pointer to the semaphore if one is found,
  119.     NULL otherwise.
  120.  
  121.     N.B. The amiga.lib and c[32].lib bindings for this function
  122.     are broken.  You must include your own bindings for this
  123.     to work.  See example.
  124.  
  125.  
  126. ObtainSemaphore(SignalSemaphore)
  127. struct SignalSemaphore *SignalSemaphore;
  128.  
  129.     This function locks the given semaphore for your use.  If the
  130.     semaphore is currently in use by someone else it blocks until
  131.     it is Release'd by the current owner.  A nesting count is
  132.     maintained if you try to Obtain a semaphore that you already
  133.     have.
  134.  
  135. ReleaseSemaphore(SignalSemaphore)
  136. struct SignalSemaphore *SignalSemaphore;
  137.  
  138.     This function frees the given semaphore for use by someone
  139.     else.  If you Obtained the semaphore more than once the
  140.     the nesting count is simply decremented rather than
  141.     actually Releasing the semaphore.  Bad things happen if
  142.     you Release more times than you Obtain.
  143.  
  144.  
  145. AttemptSemaphore(SignalSemaphore)
  146. struct SignalSemaphore *SignalSemaphore;
  147.  
  148.     This function tries to Obtain the semaphore provided.  If this
  149.     can be done it locks the semaphore and returns true.  If the
  150.     semaphore is currently in use by someone else it returns false.
  151.     Use this function if you don't want to block your task waiting
  152.     for a semaphore.
  153.  
  154.  
  155. ObtainSemaphoreList(SemaphoreList)
  156. struct SemaphoreList *SemaphoreList;
  157.  
  158. ReleaseSemaphoreList(SemaphoreList)
  159. struct SemaphoreList *SemaphoreList;
  160.  
  161.     Haven't played with these two yet... They're used for locking
  162.     several semaphores in one atomic action.  This ability can
  163.     be used to prevent deadlock.
  164.  
  165. ----
  166.  
  167. Note:
  168.     The Kernel doesn't seem to do any kind of deadlock prevention
  169.     or recovery.  This means you have to decide for yourself if
  170.     deadlock is an issue in your application.  There are several
  171.     good books which deal with deadlock avoidance and so forth
  172.     so I won't go into that here.
  173.